﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Collections;
using System.Net.NetworkInformation;
using System.Net;
using System.Windows.Forms;
using System.IO;

namespace jNetServer
{
    public class BaseWebServer
    {
        /// <summary>
        /// MINI WEB SERVER
        /// </summary>
        public BaseWebServer()
        {
            this._index = "default.html";
            this._root = Application.StartupPath + @"\www";
            this._isAutoPort = true;
            this._confTemp = Application.StartupPath + @"\my.conf";
            this._serverRoot = Application.StartupPath + @"\nginx\";
            this._port = AutoPort(80);
        }

        /// <summary>
        /// MINI WEB SERVER
        /// </summary>
        /// <param name="serverRoot">nginx根目录</param>
        /// <param name="confTemp">nginx配置模版</param>
        /// <param name="root">站点根目录</param>
        /// <param name="port">服务端口号</param>
        /// <param name="autoPort">是否自动检测可用端口</param>
        /// <param name="index">站点默认文档</param>
        public BaseWebServer(string serverRoot, string confTemp, string root, int port, bool autoPort, string index)
        {
            Port = port;
            Indexs = index;
            WebRoot = root;
            IsAutoPort = autoPort;
            ConfTemp = confTemp;
            ServerRoot = serverRoot;

            if (IsAutoPort)
            {
                this.Port = AutoPort(port);
            }
        }

        /// <summary>
        /// 开始服务
        /// </summary>
        public virtual bool Start()
        {
            string msg = ReloadConf();

            if (msg == "加载完成")
            {
                try
                {
                    _serverProcess = new Process();
                    _serverProcess.StartInfo.WorkingDirectory = this._serverRoot;
                    _serverProcess.StartInfo.FileName = this._serverRoot + @"\nginx.exe";
                    _serverProcess.StartInfo.RedirectStandardInput = true; //重定向标准输入 
                    _serverProcess.StartInfo.RedirectStandardOutput = true; //重定向标准输出 
                    _serverProcess.StartInfo.RedirectStandardError = true; //重定向错误输出
                    _serverProcess.StartInfo.UseShellExecute = false;
                    _serverProcess.StartInfo.CreateNoWindow = true;
                    _serverProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                    return _serverProcess.Start();
                }
                catch
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 打开主页
        /// </summary>
        public virtual void OpenHome()
        {
            string url = string.Format("http://localhost:{0}", Port);
            ServerWebBrowser = Process.Start(url);
        }

        /// <summary>
        /// 停止服务
        /// </summary>
        public void Stop()
        {
            KillServer();

            if (_serverProcess != null)
            {
                _serverProcess.Close();
                _serverProcess.Dispose();
            }
        }

        /// <summary>
        /// 关闭服务器的进程
        /// </summary>
        void KillServer()
        {
            try
            {
                Process[] myProcesses = Process.GetProcesses();

                string serverName = Path.GetFileNameWithoutExtension(_serverRoot);

                foreach (Process myProcess in myProcesses)
                {
                    if (serverName == myProcess.ProcessName)
                    {
                        myProcess.Kill();
                        //return;
                    }
                }
            }
            catch
            { }
        }

        /// <summary>
        /// 重新加载配置文件
        /// </summary>
        /// <returns></returns>
        public string ReloadConf()
        {
            string confpath = _serverRoot + @"\conf\";
            string conffilename = _serverRoot + @"\conf\nginx.conf";

            try
            {
                if (!Directory.Exists(confpath))
                {
                    return confpath + "目录不存在";
                }

                if (File.Exists(conffilename))
                {
                    File.Delete(conffilename);
                }

                using (StreamWriter nginxConfSr = File.CreateText(conffilename))
                {
                    using (StreamReader nginxConfTempSr = new StreamReader(_confTemp, Encoding.Default))
                    {
                        string nginxConfTempLine;

                        while ((nginxConfTempLine = nginxConfTempSr.ReadLine()) != null)
                        {
                            if (nginxConfTempLine.Contains("$port"))
                            {
                                nginxConfTempLine = nginxConfTempLine.Replace("$port", _port.ToString());
                            }
                            if (nginxConfTempLine.Contains("$root"))
                            {
                                nginxConfTempLine = nginxConfTempLine.Replace("$root", _root.ToString());
                            }
                            if (nginxConfTempLine.Contains("$index"))
                            {
                                nginxConfTempLine = nginxConfTempLine.Replace("$index", _index.ToString());
                            }

                            nginxConfSr.WriteLine(nginxConfTempLine);
                        }
                    }
                }
                return "加载完成";
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        #region 字段属性

        private string _root;
        /// <summary>
        /// 站点根目录
        /// </summary>
        public string WebRoot
        {
            get { return _root; }
            set { _root = value; }
        }

        private int _port;
        /// <summary>
        /// 起始端口号
        /// </summary>
        public int Port
        {
            get { return _port; }
            set { _port = value; }
        }

        private string _index;
        /// <summary>
        /// 默认文档名
        /// </summary>
        public string Indexs
        {
            get { return _index; }
            set { _index = value; }
        }

        private Process _serverProcess;
        /// <summary>
        /// nginx的服务进程
        /// </summary>
        public Process ServerProcess
        {
            get { return _serverProcess; }
            set { _serverProcess = value; }
        }

        private Process _serverWebBrowser;
        /// <summary>
        /// 默认打开的浏览器进程
        /// </summary>
        public Process ServerWebBrowser
        {
            get { return _serverWebBrowser; }
            set { _serverWebBrowser = value; }
        }

        private bool _isAutoPort;
        /// <summary>
        /// 是否自动检测可用端口
        /// </summary>
        public bool IsAutoPort
        {
            get { return _isAutoPort; }
            set { _isAutoPort = value; }
        }

        private string _confTemp;
        /// <summary>
        /// 配置模版文件
        /// </summary>
        public string ConfTemp
        {
            get { return _confTemp; }
            set { _confTemp = value; }
        }

        private string _serverRoot;
        /// <summary>
        /// 服务程序根目录
        /// </summary>
        public string ServerRoot
        {
            get { return _serverRoot; }
            set { _serverRoot = value; }
        }


        #endregion

        #region 私有方法

        /// <summary>
        /// 自动计算未被使用的最小端口号，默认从80开始
        /// </summary>
        /// <returns></returns>
        public int AutoPort(int startPort)
        {
            int myPort = 0;

            int MAX_PORT = 65535; //系统tcp/udp端口数最大是65535 

            int BEGIN_PORT = startPort;//从这个端口开始检测 

            for (int i = BEGIN_PORT; i < MAX_PORT; i++)
            {
                if (PortIsAvailable(i))
                {
                    myPort = i;
                    break;
                }
            }
            return myPort;
        }

        /// <summary>
        /// 检查指定端口号是否已用
        /// </summary>
        /// <param name="port">预检查的端口号</param>
        /// <returns></returns>
        private bool PortIsAvailable(int port)
        {
            bool isAvailable = true;

            IList portUsed = PortIsUsed();

            foreach (int p in portUsed)
            {
                if (p == port)
                {
                    isAvailable = false; break;
                }
            }

            return isAvailable;
        }

        /// <summary>
        /// 获取本地计算机已用端口号列表
        /// </summary>
        /// <returns></returns>
        private IList PortIsUsed()
        {
            //获取本地计算机的网络连接和通信统计数据的信息 
            IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();

            //返回本地计算机上的所有Tcp监听程序 
            IPEndPoint[] ipsTCP = ipGlobalProperties.GetActiveTcpListeners();

            //返回本地计算机上的所有UDP监听程序 
            IPEndPoint[] ipsUDP = ipGlobalProperties.GetActiveUdpListeners();

            //返回本地计算机上的Internet协议版本4(IPV4 传输控制协议(TCP)连接的信息。 
            TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();

            IList allPorts = new ArrayList();
            foreach (IPEndPoint ep in ipsTCP) allPorts.Add(ep.Port);
            foreach (IPEndPoint ep in ipsUDP) allPorts.Add(ep.Port);
            foreach (TcpConnectionInformation conn in tcpConnInfoArray) allPorts.Add(conn.LocalEndPoint.Port);

            return allPorts;
        }

        #endregion
    }
}
